package com.chen.service.impl;

import com.chen.common.utils.ThreadLocalUtil;
import com.chen.mapper.*;
import com.chen.popj.entity.*;
import com.chen.popj.vo.ContestLeaderboardVO;
import com.chen.service.ContestLeaderboardService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.*;

@Service
public class ContestLeaderboardServiceImpl implements ContestLeaderboardService {

    @Autowired
    ContestLeaderboardMapper contestLeaderboardMapper;

    @Autowired
    ContestCodeSubmitMapper contestCodeSubmitMapper;

    @Autowired
    ContestProblemMapper contestProblemMapper;

    @Autowired
    ContestMapper contestMapper;

    @Autowired
    UserMapper userMapper;

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    /**
     * 获取比赛排行榜信息
     *
     * @param contestId
     * @return
     */
    @Override
    public List<ContestLeaderboardVO> getContestLeaderboard(Integer contestId) {
        List<ContestLeaderboard> contestLeaderboardList = contestLeaderboardMapper.getByContestId(contestId);
        Map<Integer, List<ContestLeaderboard>> contestLeaderboardListMap = new HashMap<>();
//        ArrayList<ContestLeaderboardVO> contestLeaderboardVOArrayList = new ArrayList<>();
        HashSet<Integer> hashSet = new HashSet<>();
        for (ContestLeaderboard contestLeaderboard : contestLeaderboardList) {
            Integer userId = contestLeaderboard.getUserId();
            hashSet.add(userId);
            List<ContestLeaderboard> leaderboardsMap = contestLeaderboardListMap.get(userId);
            if (leaderboardsMap == null) {
                ArrayList<ContestLeaderboard> arrayList = new ArrayList<>();
                arrayList.add(contestLeaderboard);
                contestLeaderboardListMap.put(userId, arrayList);
            } else {
                leaderboardsMap.add(contestLeaderboard);
                contestLeaderboardListMap.put(userId, leaderboardsMap);
            }
        }
        int acCount = 0;
        int wrongTotalCount = 0;
        long totalPenalty = 0;
        int orderId = 0;
        Contest contestInfo = contestMapper.getContestInfo(contestId);
        // 比赛开始时间
        LocalDateTime contestStartTime = contestInfo.getContestStartTime();
        PriorityQueue<ContestLeaderboardVO> contestLeaderboardVOPriorityQueue = new PriorityQueue<>((c1, c2) ->
                Long.compare(c2.getPenalty(), c1.getPenalty()));
        LocalDateTime time = null;
        for (Integer i : hashSet) {
            acCount = 0;
            wrongTotalCount = 0;
            totalPenalty = 0;
            orderId = 0;
            List<ResultList> resultListArrayList = new ArrayList<>();
            String username = null;
            List<ContestLeaderboard> leaderboardList = contestLeaderboardListMap.get(i);
            for (ContestLeaderboard contestLeaderboard : leaderboardList) {
                if (username == null) {
                    Integer userId = contestLeaderboard.getUserId();
                    username = userMapper.queryUsernameById(userId);
                }
                if (contestLeaderboard.getSubmitTime() == null) {
                    time = contestStartTime;
                } else {
                    time = contestLeaderboard.getSubmitTime();
                }
                Duration duration = Duration.between(contestStartTime, time);
                long hours = duration.toHours() % 24; // 获取小时数（24小时制内）
                long minutes = duration.toMinutes() % 60; // 获取分钟数
                long seconds = duration.getSeconds() % 60; // 获取秒数
//                Duration penaltyDuration = Duration.ofHours(hours).plusMinutes(minutes).plusSeconds(seconds);
                totalPenalty += duration.getSeconds();
                // 使用 String.format 格式化时间
                String penalty = String.format("%02d:%02d:%02d", hours, minutes, seconds);
                boolean isAc = "Accepted".equals(contestLeaderboard.getResult());
                wrongTotalCount += contestLeaderboard.getWrongCount();
                if (isAc) {
                    acCount++;
                }
                orderId++;
                ResultList resultList = new ResultList();
                resultList.setId(orderId);
                resultList.setTime(penalty);
                resultList.setResult(contestLeaderboard.getResult());
                resultList.setWrongCount(contestLeaderboard.getWrongCount());
                resultListArrayList.add(resultList);
            }
            totalPenalty += (wrongTotalCount * 20L * 60L);
            long penaltySeconds = calculateScore(acCount, totalPenalty);
            long hours = totalPenalty / 3600; // 计算小时数
            long remainingSeconds = totalPenalty % 3600; // 计算剩余的秒数
            long minutes = remainingSeconds / 60; // 计算分钟数
            long seconds = remainingSeconds % 60; // 计算最终的秒数
            // 使用 String.format 格式化时间
            String totalTime = String.format("%02d:%02d:%02d", hours, minutes, seconds);
            ContestLeaderboardVO contestLeaderboardVO = ContestLeaderboardVO.builder()
                    .total(contestLeaderboardList.size())
                    .userName(username)
                    .totalTime(totalTime)
                    .acceptedNumber(acCount)
                    .resultList(resultListArrayList)
                    .penalty(penaltySeconds)
                    .build();
//            ValueOperations<String, String> opsForValue = stringRedisTemplate.opsForValue();
//            opsForValue.
            contestLeaderboardVOPriorityQueue.add(contestLeaderboardVO);

        }
//        if (!contestLeaderboardVOPriorityQueue.isEmpty()) {
//            contestLeaderboardVOPriorityQueue.
//                    contestLeaderboardVOArrayList.add(contestLeaderboardVO);
//        }
        ArrayList<ContestLeaderboardVO> contestLeaderboardVOArrayList = new ArrayList<>(contestLeaderboardVOPriorityQueue);

        return contestLeaderboardVOArrayList;
//        return contestLeaderboardVO;
//        System.out.println(contestLeaderboardListMap);
//        Map<String, Object> threadLocalMap = ThreadLocalUtil.get();
//        Integer username = (Integer) threadLocalMap.get("username");
//        List<ContestLeaderboard> contestLeaderboardList = contestLeaderboardMapper.getByContestId(contestId);
////        System.out.println(contestLeaderboardList);
//        List<ResultList> resultListArrayList = new ArrayList<>();
//        int acCount = 0;
//        int wrongTotalCount = 0;
//        long totalPenalty = 0;
//        Contest contestInfo = contestMapper.getContestInfo(contestId);
//        // 比赛开始时间
//        LocalDateTime contestStartTime = contestInfo.getContestStartTime();
//        for (ContestLeaderboard contestLeaderboard : contestLeaderboardList) {
////            contestLeaderboardHashMap.put(contestLeaderboard.)
//            Duration duration = Duration.between(contestStartTime, contestLeaderboard.getSubmitTime());
//            long hours = duration.toHours() % 24; // 获取小时数（24小时制内）
//            long minutes = duration.toMinutes() % 60; // 获取分钟数
//            long seconds = duration.getSeconds() % 60; // 获取秒数
//            Duration penaltyDuration = Duration.ofHours(hours).plusMinutes(minutes).plusSeconds(seconds);
//            totalPenalty += duration.getSeconds();
//            if (contestLeaderboard.)
//            // 使用 String.format 格式化时间
//            String penalty = String.format("%02d:%02d:%02d", hours, minutes, seconds);
////            System.out.println(penalty);
//            ResultList resultList = ResultList.builder()
//                    .penalty(penalty)
//                    .result(contestLeaderboard.getResult())
//                    .wrongCount(contestLeaderboard.getWrongCount())
//                    .build();
//            resultListArrayList.add(resultList);
//            if (contestLeaderboard.getIsFirstAc() == 0 && "Accepted".equals(contestLeaderboard.getResult())) {
//            }
//
//        }
        // 分数 = 解题数 * 1e9 + (1e9 - 罚时) 计算每个用户的分数。
//        ContestLeaderboardVO contestLeaderboardVO = ContestLeaderboardVO.builder()
//                .total(contestLeaderboardList.size())
//                .userName(username)
//                .problemId()
//                .totalTime()
//                .acceptedNumber()
//                .resultLists()
//                .build();
//        return null;
    }

    /**
     * 用户报名比赛
     *
     * @param contestId
     * @param userId
     */
    @Override
    public void contestRegister(Integer contestId, Integer userId) {
        List<ContestProblem> contestProblemList = contestProblemMapper.getByContestId(contestId);
        ArrayList<ContestLeaderboard> contestLeaderboardArrayList = new ArrayList<>();
        for (ContestProblem contestProblem : contestProblemList) {
            ContestLeaderboard contestLeaderboard = ContestLeaderboard.builder()
                    .contestId(contestId)
                    .problemId(contestProblem.getProblemId())
                    .userId(userId)
                    .build();
            contestLeaderboardArrayList.add(contestLeaderboard);
        }
        for (ContestLeaderboard contestLeaderboard : contestLeaderboardArrayList) {
            System.out.println(contestLeaderboard);
        }
        contestLeaderboardMapper.save(contestLeaderboardArrayList);
    }

    /**
     * 修改用户排行榜信息
     *
     * @param problemSubmitId
     */
    @Override
    public void updateContestLeaderboard(Integer problemSubmitId) {
        ContestCodeSubmit contestCodeSubmit = contestCodeSubmitMapper.getByProblemSubmitId(problemSubmitId);
        short isFirstAc = 0;
        if (contestCodeSubmit.getResult().contains("Accepted") && contestCodeSubmit.getWrongCount() == 0) {
            isFirstAc = 1;
        }
        int wrongCount = 0;
        if (!contestCodeSubmit.getResult().contains("Accepted")) {
            wrongCount = 1;
        }

        ContestLeaderboard contestLeaderboard = ContestLeaderboard.builder()
                .contestId(contestCodeSubmit.getContestId())
                .problemId(contestCodeSubmit.getProblemId())
                .problemSubmitId(contestCodeSubmit.getProblemSubmitId())
                .userId(contestCodeSubmit.getUserId())
                .isFirstAc(isFirstAc)
                .wrongCount(wrongCount)
                .submitTime(contestCodeSubmit.getSubmitTime())
                .result(contestCodeSubmit.getResult())
                .build();
        contestLeaderboardMapper.update(contestLeaderboard);
    }

    public long calculateScore(int solvedProblems, long penaltySeconds) {
        // 将罚时转换为秒数
//        long penaltySeconds = penalty.getSeconds(); // 这将忽略纳秒部分，如果需要更高精度，可以使用toMillis()然后除以1000

        // 注意：如果罚时可能超过Duration.ofSeconds(Long.MAX_VALUE)，则这里需要特殊处理
        // 但在实际竞赛环境中，罚时通常不会这么大
        // 计算分数
        long score = (long) ((solvedProblems * 1e9) + (1e9 - penaltySeconds));
        // 返回分数
        return score;
    }
}
